#include "KinectController.h"


KinectController::KinectController(void)
{
	g_bPause = false;
	g_bRecord = false;
	g_bQuit = false;
	g_bCalibrated = FALSE;
}


KinectController::~KinectController(void)
{
}

void KinectController::setSceneImg( SceneImg *sceneImg )
{
	m_sceneImg = sceneImg;
}

void KinectController::StopCapture()
{
	g_bRecord = false;
	if (g_pRecorder != NULL)
	{
		g_pRecorder->RemoveNodeFromRecording(m_sceneImg->m_DepthGenerator);
		g_pRecorder->Release();
		delete g_pRecorder;
	}
	g_pRecorder = NULL;
}

void KinectController::CleanupExit()
{
	if (g_pRecorder)
		g_pRecorder->RemoveNodeFromRecording(m_sceneImg->m_DepthGenerator);
	StopCapture();

	m_sceneImg->m_Context.Shutdown();
	exit (1);
}

void KinectController::StartCapture()
{
	char recordFile[256] = {0};
	time_t rawtime;
	struct tm *timeinfo;

	time(&rawtime);
	timeinfo = localtime(&rawtime);
	XnUInt32 size;
	xnOSStrFormat(recordFile, sizeof(recordFile)-1, &size,
		"%d_%02d_%02d[%02d_%02d_%02d].oni",
		timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

	if (g_pRecorder != NULL)
	{
		StopCapture();
	}

	XnStatus nRetVal = XN_STATUS_OK;
	g_pRecorder = new xn::Recorder;

	m_sceneImg->m_Context.CreateAnyProductionTree(XN_NODE_TYPE_RECORDER, NULL, *g_pRecorder);
	START_CAPTURE_CHECK_RC(nRetVal, "Create recorder");

	nRetVal = g_pRecorder->SetDestination(XN_RECORD_MEDIUM_FILE, recordFile);
	START_CAPTURE_CHECK_RC(nRetVal, "set destination");
	nRetVal = g_pRecorder->AddNodeToRecording(m_sceneImg->m_DepthGenerator, XN_CODEC_16Z_EMB_TABLES);
	START_CAPTURE_CHECK_RC(nRetVal, "add node");
	g_bRecord = true;
}

void KinectController::CalibrationEndedCB( xn::SkeletonCapability& skeleton, XnUserID user, XnBool bSuccess, void* cxt )
{
	if (bSuccess)
	{
		if (!g_bCalibrated)
		{
			m_sceneImg->m_UserGenerator.GetSkeletonCap().SaveCalibrationData(user, 0);
			m_sceneImg->setPlayer(user);
			m_sceneImg->m_UserGenerator.GetSkeletonCap().StartTracking(user);
			g_bCalibrated = TRUE;
		}

		XnUserID aUsers[10];
		XnUInt16 nUsers = 10;
		m_sceneImg->m_UserGenerator.GetUsers(aUsers, nUsers);
		for (int i = 0; i < nUsers; ++i)
			m_sceneImg->m_UserGenerator.GetPoseDetectionCap().StopPoseDetection(aUsers[i]);
	}
}

void KinectController::ReadNextData()
{
	if (!g_bPause)
	{
		// Read next available data
		m_sceneImg->m_Context.WaitOneUpdateAll(m_sceneImg->m_DepthGenerator);
	}
}

void KinectController::IdleClean()
{
	if (g_bQuit) {
		CleanupExit();
	}
}

void KinectController::RecordChange()
{
	if (g_pRecorder == NULL)
		StartCapture();
	else
		StopCapture();
	printf("Record turned %s\n", g_pRecorder ? "on" : "off");
}

int KinectController::KinectInit()
{
	XnStatus rc = XN_STATUS_OK;
	xn::EnumerationErrors errors;

	rc = m_sceneImg->m_Context.InitFromXmlFile(SAMPLE_XML_PATH);
	CHECK_ERRORS(rc, errors, "InitFromXmlFile");
	CHECK_RC(rc, "InitFromXml");

	rc = m_sceneImg->m_Context.FindExistingNode(XN_NODE_TYPE_DEPTH, m_sceneImg->m_DepthGenerator);
	CHECK_RC(rc, "Find depth generator");
	rc = m_sceneImg->m_Context.FindExistingNode(XN_NODE_TYPE_USER, m_sceneImg->m_UserGenerator);
	CHECK_RC(rc, "Find user generator");
	// 2011-11-23
	rc = m_sceneImg->m_Context.FindExistingNode(XN_NODE_TYPE_IMAGE, m_sceneImg->m_ImageGenerator);
	CHECK_RC(rc, "Find image generator");
	m_sceneImg->m_DepthGenerator.GetAlternativeViewPointCap().SetViewPoint(m_sceneImg->m_ImageGenerator);

	if (!m_sceneImg->m_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON) ||
		!m_sceneImg->m_UserGenerator.IsCapabilitySupported(XN_CAPABILITY_POSE_DETECTION))
	{
		printf("User generator doesn't support either skeleton or pose detection.\n");
		return XN_STATUS_ERROR;
	}

	m_sceneImg->m_UserGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL);

	rc = m_sceneImg->m_Context.StartGeneratingAll();
	CHECK_RC(rc, "StartGenerating");
}

void KinectController::RegisterCB()
{
	XnCallbackHandle hUserCBs, hCalibrationCBs, hPoseCBs;
	m_sceneImg->m_UserGenerator.RegisterUserCallbacks(NewUser, LostUser, NULL, hUserCBs);
	m_sceneImg->m_UserGenerator.GetSkeletonCap().RegisterCalibrationCallbacks(CalibrationStarted, CalibrationEnded, NULL, hCalibrationCBs);
	m_sceneImg->m_UserGenerator.GetPoseDetectionCap().RegisterToPoseCallbacks(PoseDetected, NULL, NULL, hPoseCBs);
}
